import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// class Square extends React.Component {
//     render() {
//         return (
//             <button className="square" onClick={() => this.props.onClick()}>
//                 {this.props.value}
//             </button>
//         );
//     }
// }

// 方块函数组件
function Square(props) {
    return (
        // onClick事件触发时调用父组件的onClick函数
        <button className={`square ${props.isHighlight ? "highlight" : ""} ${props.isWin ? "win" : ""}`}
                onClick={props.onClick}>
            {props.value}
        </button>
    )
}

// 计算是否胜出函数
function calculateWinner(squares) {
    // 所有胜利情况
    const lines = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
    ];

    // 逐一匹配胜利情况
    for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
            // 返回胜利的位置数组
            return [a, b, c];
        }
    }
    return [];
}

// 游戏板组件类
class Board extends React.Component {

    // 渲染board-row函数
    renderBoardRows() {
        let boardRows = [];
        for (let i = 0; i < 3; i++) {
            boardRows.push(<div className="board-row">
                {this.renderSquares(i * 3)}
            </div>)
        }
        return boardRows;
    }

    // 渲染方块组件函数
    renderSquares(startIndex) {
        let squares = [];
        for (let i = 0; i < 3; i++) {
            const index = startIndex
            squares.push(<Square value={this.props.squares[index]}
                                 isHighlight={this.props.highlightSquare === index}
                                 isWin={calculateWinner(this.props.squares).includes(index)}
                                 onClick={() => this.props.onClick(index)}/>)
            startIndex++;
        }
        return squares;
    }

    // 游戏板组件渲染函数
    render() {
        return (
            <div>
                {this.renderBoardRows()}
            </div>
        );
    }
}

// 游戏组件类
class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            history: [
                {
                    // 方块状态数组
                    squares: Array(9).fill(null),
                    // 最后一步坐标
                    lastStep: []
                }
            ],
            // 历史记录排序
            isReverseOrder: false,
            // 当前步骤数
            stepNumber: 0,
            // 下一个是否是X
            xIsNext: true,
            // 需要高亮的方块索引
            highlightSquare: null
        };
    }

    // 处理点击事件
    handleClick(i) {
        // 截取历史数组，丢弃之后的步骤
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[history.length - 1];
        // 获取方块状态数组备份
        const squares = current.squares.slice();
        // 如果已经落子，或者已经胜利，则无需修改状态
        if (squares[i] || calculateWinner(squares).length > 0) {
            return;
        }
        // 修改状态
        squares[i] = this.state.xIsNext ? 'X' : 'O';
        this.setState({
            history: history.concat([{
                squares: squares,
                lastStep: i
            }]),
            stepNumber: history.length,
            xIsNext: !this.state.xIsNext,
        });
    }

    // 调到某一步函数
    jumpTo(num) {
        this.setState({
            stepNumber: num,
            xIsNext: (num % 2) === 0,
        });
    }

    // 高亮方块
    highlight(lastStep) {
        this.setState({
            highlightSquare: lastStep
        })
    }

    // 切换排序
    triggerOrder() {
        this.setState({
            isReverseOrder: !this.state.isReverseOrder
        })
    }

    render() {
        const history = this.state.history;
        // 获取当前步骤的方块状态，在时间旅行跳转时，会自动更新
        const current = history[this.state.stepNumber];
        // 判断是否获胜
        const winnerSquares = calculateWinner(current.squares);
        // 游戏状态
        let status;
        if (winnerSquares.length > 0) {
            status = '获胜者: ' + current.squares[winnerSquares[0]];
        } else if (!current.squares.includes(null)) {
            status = '获胜者: 平局';
        } else {
            status = '当前玩家: ' + (this.state.xIsNext ? 'X' : 'O');
        }

        // 渲染历史列表
        let moves = history.map((step, num) => {
            // 计算坐标
            const lastStepCoordinate = [parseInt(step.lastStep / 3), step.lastStep % 3]
            const desc = num ?
                '跳转到 #第' + num + '步，位置(' + lastStepCoordinate + ')' :
                '跳转到 #游戏开始';
            return (
                <li key={num}>
                    <button onClick={() => this.jumpTo(num)}
                            onMouseEnter={() => this.highlight(step.lastStep)}
                            onMouseLeave={() => this.highlight()}>{desc}</button>
                </li>
            );
        });

        // 是否倒序
        if (this.state.isReverseOrder) {
            moves.reverse()
        }

        return (
            <div className="game">
                <div className="game-board">
                    <Board squares={current.squares} highlightSquare={this.state.highlightSquare}
                           onClick={(i) => this.handleClick(i)}/>
                </div>
                <div className="game-info">
                    <div>{status}</div>
                    <ol>
                        <button onClick={() => this.triggerOrder()}>{this.state.isReverseOrder ? "倒序" : "正序"}</button>
                        {moves}
                    </ol>
                </div>
            </div>
        );
    }
}

// 将游戏组件挂载到root
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Game/>);
